// 
// Performs various reporting functions
//
// Do not change the code in this file, as doing so
// could cause your submission to be graded incorrectly
//

#include <iostream>
#include <fstream>
#include <iomanip>
#include <math.h>
#include "types.h"

using namespace std;

double gflops(int n, int niter, double time){
    int n2 = n*n;
    long long int updates = (long long ) n2 * (long long) niter;
    long long int flops = 28 * updates;
    double flop_rate = (double) flops / time;
    return ( flop_rate/1.0e9);
}

_DOUBLE_ stats(_DOUBLE_ **E, int m, int n, _DOUBLE_ *_mx);

void ReportEnd(_DOUBLE_ T,int niter, _DOUBLE_ **E_prev, int m,int n, int bx, int by, double t0, int prefer_l1){
    // The log file
    // Do not change the file name or remove this call
    ofstream logfile("Log.txt",ios::out);
    _DOUBLE_ mx, l2norm;
    l2norm = stats(E_prev,m,n,&mx);

    double gf = gflops(n+1, niter, t0);

    logfile << "   M x N, BX, BY, SimT, ";
    logfile <<  "#iter, T_p, Gflops, Linf, L2, L1/$, Prec" << endl;
    logfile << "># " << m << " " << n << " ";
    logfile << " " << bx << " " << by << " ";
    logfile.precision(6);
    logfile << T << " ";
    logfile << niter << " ";
    logfile.precision(4);
    logfile << t0 << " "  << gf << " ";

    logfile.unsetf(ios::fixed);
    logfile.setf(ios::scientific);
    logfile.precision(5);
    logfile << mx << " " << l2norm;
    if (prefer_l1)
        logfile << " L1";
    else
        logfile << " SM";
#ifndef _DOUBLE
    logfile << " SP";
#else
    logfile << " DP";
#endif
    logfile << endl;
    logfile.close();


}

void ReportStart(_DOUBLE_ dt, _DOUBLE_ T, int m, int n, int bx, int by, int prefer_l1){
  
#ifndef _DOUBLE
    cout << "Using Single precision arithmetic" << endl;
#else
    cout << "Using Double precision arithmetic" << endl;
#endif

    if (prefer_l1)
        cout << "Prefer L1 Cache over Shared memory" << endl;
    else
        cout << "Prefer Shared Memory over  Cache" << endl;

    cout << "dt= " << dt << ", T = " << T << endl;
    cout << " *** The code will run for approximately " << (int)ceil(T/dt) << " timesteps" << endl;
    cout << "m x n = " << m << " x " << n << endl;
    cout << "threads block geometry: " << bx << " x " << by << endl;
}

void printTOD(string mesg)
{
        time_t tim = time(NULL);
        string s = ctime(&tim);
        if (mesg.length() ==  0) 
            cout << "Time of day: " << s.substr(0,s.length()-1) << endl;
        else {
            cout << "[" << mesg << "] " ;
            cout << s.substr(0,s.length()-1) << endl;
        }
        cout << endl;
}

